package upgrade

import (
	"sort"
	"strings"

	"gddgame.cc/galaxy"
	"gddgame.cc/galaxy/asteroid"
	"gddgame.cc/galaxy/asteroid/cluster"
	"gddgame.cc/galaxy/binocle/logic"
	"gddgame.cc/galaxy/utils"
)

type Upgrade func(version string)

// 一台机器通知一台机器升级
// 升级完的机器再次通知后续机器升级
// 如果升级到最初的机器，则升级完成
func bindVersion(version string, handler Upgrade, system logic.System) {
	versionList := parseVersion(version)
	if handler == nil {
		handler = func(version string) {
			galaxy.Exit()
		}
	}
	system.MountNode(func(node cluster.Node) {
		client := system.Client()
		node.On("version", func(message asteroid.Message) {
			startNode := message.Data().(string)
			if startNode == client.CurrentNode() {
				return
			}
			currentVersion := message.Read(1).(string)
			node.Debugf("Node:%s => version(%s)", message.GetFrom(), currentVersion)
			if version != currentVersion {
				currentList := parseVersion(currentVersion)
				for i := 0; i < len(currentList); i++ {
					if i >= len(versionList) {
						node.Error("Version length miss match", message.GetFrom(), currentVersion)
						return
					}
					if currentList[i] > versionList[i] {
						// 执行升级
						handler(currentVersion)
					} else {
						// 本机版本最新，则已自己为节点发布更新
						noticeVersion(client, client.CurrentNode(), version)
					}
				}
			}
		})
	})
	system.MountClient(func(client *cluster.Client) {
		noticeVersion(client, client.CurrentNode(), version)
	})
}

func noticeVersion(client *cluster.Client, node, version string) {
	// 从排序后的节点列表中本节点选择后一位进行消息发送
	nodes := client.AllNode()
	sort.Strings(nodes)
	index := sort.SearchStrings(nodes, client.CurrentNode())
	if index == len(nodes)-1 {
		// 如果是最后一位，选择第一位进行发送
		index = 0
	}
	if index != len(nodes) {
		client.Direct(nodes[index]).List(node, version).Send("version")
	}
}

func parseVersion(version string) []int {
	versionList := strings.Split(version, ".")
	intList := make([]int, len(versionList))
	for key := range versionList {
		intList[key] = utils.ToInt(versionList[key])
	}
	return intList
}
